Chapter 23

Project: Simple Quiz App

Session 23

Learning Objectives

By the end of this chapter, you will be able to:

1

Project Overview

Project Goal

Build a "Flutter Knowledge Quiz" app that presents multiple-choice questions about Flutter and Dart. Users can answer questions, see their progress, view results, and retake the quiz.

Features to Implement

  • Multiple-choice questions with 4 options
  • Question navigation (next/previous)
  • Progress indicator
  • Score calculation
  • Results screen with detailed feedback
  • Timer for each question (optional)
  • Quiz restart functionality
2

Project Setup

Step 1: Create Project

flutter create quiz_app
cd quiz_app

Step 2: Add Dependencies

Update pubspec.yaml:

pubspec.yaml

name: quiz_app
description: A Flutter quiz application
version: 1.0.0+1

environment:
  sdk: '>=3.0.0 <4.0.0'

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.6

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^3.0.0

flutter:
  uses-material-design: true

Step 3: Install Dependencies

flutter pub get
3

Project Structure

Suggested Folder Layout

lib/
  main.dart
  models/
    question.dart
    quiz_result.dart
  data/
    quiz_data.dart
  screens/
    home_screen.dart
    quiz_screen.dart
    result_screen.dart
  widgets/
    question_card.dart
    option_button.dart
    progress_indicator.dart
    score_display.dart
4

Creating Question Model

lib/models/question.dart

class Question {
  final String id;
  final String questionText;
  final List options;
  final int correctAnswerIndex;
  final String? explanation;

  Question({
    required this.id,
    required this.questionText,
    required this.options,
    required this.correctAnswerIndex,
    this.explanation,
  });

  bool isCorrect(int selectedIndex) {
    return selectedIndex == correctAnswerIndex;
  }

  String get correctAnswer => options[correctAnswerIndex];
}
5

Creating Quiz Result Model

lib/models/quiz_result.dart

class QuizResult {
  final int totalQuestions;
  final int correctAnswers;
  final int wrongAnswers;
  final Map userAnswers; // questionId -> selectedOptionIndex
  final DateTime completedAt;

  QuizResult({
    required this.totalQuestions,
    required this.correctAnswers,
    required this.wrongAnswers,
    required this.userAnswers,
    required this.completedAt,
  });

  double get percentage => (correctAnswers / totalQuestions) * 100;

  String get grade {
    if (percentage >= 90) return 'A+';
    if (percentage >= 80) return 'A';
    if (percentage >= 70) return 'B';
    if (percentage >= 60) return 'C';
    if (percentage >= 50) return 'D';
    return 'F';
  }

  String get feedback {
    if (percentage >= 90) return 'Excellent! You have a great understanding of Flutter!';
    if (percentage >= 80) return 'Great job! You\'re doing well!';
    if (percentage >= 70) return 'Good work! Keep practicing!';
    if (percentage >= 60) return 'Not bad! Review the topics and try again!';
    return 'Keep learning! Review the material and try again!';
  }
}
6

Creating Quiz Data

lib/data/quiz_data.dart

import '../models/question.dart';

class QuizData {
  static List getFlutterQuiz() {
    return [
      Question(
        id: '1',
        questionText: 'What is Flutter?',
        options: [
          'A mobile app development framework',
          'A programming language',
          'A database management system',
          'A web server',
        ],
        correctAnswerIndex: 0,
        explanation: 'Flutter is Google\'s UI toolkit for building natively compiled applications for mobile, web, and desktop from a single codebase.',
      ),
      Question(
        id: '2',
        questionText: 'Which programming language does Flutter use?',
        options: [
          'Java',
          'Kotlin',
          'Dart',
          'Swift',
        ],
        correctAnswerIndex: 2,
        explanation: 'Flutter uses Dart, a programming language developed by Google.',
      ),
      Question(
        id: '3',
        questionText: 'What is a Widget in Flutter?',
        options: [
          'A database table',
          'A UI component',
          'A network request',
          'A file system',
        ],
        correctAnswerIndex: 1,
        explanation: 'In Flutter, everything is a widget. Widgets are the basic building blocks of Flutter apps.',
      ),
      Question(
        id: '4',
        questionText: 'What is the main difference between StatelessWidget and StatefulWidget?',
        options: [
          'StatelessWidget can change, StatefulWidget cannot',
          'StatefulWidget can change, StatelessWidget cannot',
          'They are the same',
          'StatelessWidget is faster',
        ],
        correctAnswerIndex: 1,
        explanation: 'StatefulWidget can change its state during runtime, while StatelessWidget is immutable once created.',
      ),
      Question(
        id: '5',
        questionText: 'What does "hot reload" do in Flutter?',
        options: [
          'Restarts the app',
          'Updates the UI without losing app state',
          'Deletes all data',
          'Compiles the app',
        ],
        correctAnswerIndex: 1,
        explanation: 'Hot reload allows you to update the UI instantly without losing the current app state.',
      ),
      Question(
        id: '6',
        questionText: 'What is the purpose of setState()?',
        options: [
          'To create a new widget',
          'To update the state and trigger a rebuild',
          'To delete data',
          'To navigate to a new screen',
        ],
        correctAnswerIndex: 1,
        explanation: 'setState() notifies Flutter that the state has changed and triggers a rebuild of the widget tree.',
      ),
      Question(
        id: '7',
        questionText: 'What is a Future in Dart?',
        options: [
          'A completed value',
          'A representation of a potential value or error that will be available at some time in the future',
          'A list of values',
          'A function',
        ],
        correctAnswerIndex: 1,
        explanation: 'A Future represents a potential value or error that will be available at some time in the future.',
      ),
      Question(
        id: '8',
        questionText: 'What is the purpose of async and await?',
        options: [
          'To make code synchronous',
          'To handle asynchronous operations',
          'To create loops',
          'To define classes',
        ],
        correctAnswerIndex: 1,
        explanation: 'async and await are used to handle asynchronous operations in Dart, making asynchronous code look like synchronous code.',
      ),
      Question(
        id: '9',
        questionText: 'What is a Stream in Dart?',
        options: [
          'A single value',
          'A sequence of asynchronous events',
          'A file',
          'A database',
        ],
        correctAnswerIndex: 1,
        explanation: 'A Stream is a sequence of asynchronous events that can be listened to.',
      ),
      Question(
        id: '10',
        questionText: 'What is the purpose of Navigator in Flutter?',
        options: [
          'To manage app state',
          'To navigate between screens',
          'To store data',
          'To make network requests',
        ],
        correctAnswerIndex: 1,
        explanation: 'Navigator is used to manage a stack of routes and navigate between different screens in a Flutter app.',
      ),
    ];
  }
}
7

Creating Option Button Widget

lib/widgets/option_button.dart

import 'package:flutter/material.dart';

class OptionButton extends StatelessWidget {
  final String option;
  final bool isSelected;
  final bool isCorrect;
  final bool showAnswer;
  final VoidCallback onTap;

  const OptionButton({
    Key? key,
    required this.option,
    required this.isSelected,
    required this.isCorrect,
    required this.showAnswer,
    required this.onTap,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    Color? backgroundColor;
    Color? textColor;
    IconData? icon;

    if (showAnswer) {
      if (isCorrect) {
        backgroundColor = Colors.green;
        textColor = Colors.white;
        icon = Icons.check_circle;
      } else if (isSelected && !isCorrect) {
        backgroundColor = Colors.red;
        textColor = Colors.white;
        icon = Icons.cancel;
      } else {
        backgroundColor = Colors.grey[200];
        textColor = Colors.black87;
      }
    } else {
      backgroundColor = isSelected ? Colors.blue : Colors.grey[200];
      textColor = isSelected ? Colors.white : Colors.black87;
    }

    return Padding(
      padding: EdgeInsets.symmetric(vertical: 8, horizontal: 16),
      child: InkWell(
        onTap: onTap,
        borderRadius: BorderRadius.circular(12),
        child: Container(
          padding: EdgeInsets.all(16),
          decoration: BoxDecoration(
            color: backgroundColor,
            borderRadius: BorderRadius.circular(12),
            border: Border.all(
              color: isSelected ? Colors.blue : Colors.grey[300]!,
              width: 2,
            ),
          ),
          child: Row(
            children: [
              if (icon != null) ...[
                Icon(icon, color: textColor),
                SizedBox(width: 12),
              ],
              Expanded(
                child: Text(
                  option,
                  style: TextStyle(
                    fontSize: 16,
                    color: textColor,
                    fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
8

Creating Progress Indicator Widget

lib/widgets/progress_indicator.dart

import 'package:flutter/material.dart';

class QuizProgressIndicator extends StatelessWidget {
  final int currentQuestion;
  final int totalQuestions;

  const QuizProgressIndicator({
    Key? key,
    required this.currentQuestion,
    required this.totalQuestions,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final progress = (currentQuestion + 1) / totalQuestions;

    return Padding(
      padding: EdgeInsets.all(16),
      child: Column(
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(
                'Question ${currentQuestion + 1} of $totalQuestions',
                style: TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.bold,
                ),
              ),
              Text(
                '${(progress * 100).toInt()}%',
                style: TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ],
          ),
          SizedBox(height: 8),
          LinearProgressIndicator(
            value: progress,
            backgroundColor: Colors.grey[300],
            valueColor: AlwaysStoppedAnimation(Colors.blue),
            minHeight: 8,
          ),
        ],
      ),
    );
  }
}
9

Creating Home Screen

lib/screens/home_screen.dart

import 'package:flutter/material.dart';
import 'quiz_screen.dart';
import '../data/quiz_data.dart';

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Quiz'),
        centerTitle: true,
      ),
      body: Center(
        child: Padding(
          padding: EdgeInsets.all(24),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Icon(
                Icons.quiz,
                size: 100,
                color: Colors.blue,
              ),
              SizedBox(height: 32),
              Text(
                'Flutter Knowledge Quiz',
                style: TextStyle(
                  fontSize: 28,
                  fontWeight: FontWeight.bold,
                ),
                textAlign: TextAlign.center,
              ),
              SizedBox(height: 16),
              Text(
                'Test your knowledge of Flutter and Dart!',
                style: TextStyle(
                  fontSize: 16,
                  color: Colors.grey[600],
                ),
                textAlign: TextAlign.center,
              ),
              SizedBox(height: 32),
              Card(
                child: Padding(
                  padding: EdgeInsets.all(16),
                  child: Column(
                    children: [
                      Row(
                        children: [
                          Icon(Icons.info_outline),
                          SizedBox(width: 8),
                          Text(
                            'Quiz Information',
                            style: TextStyle(
                              fontSize: 18,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                        ],
                      ),
                      SizedBox(height: 16),
                      _buildInfoRow('Total Questions', '10'),
                      _buildInfoRow('Time Limit', 'No limit'),
                      _buildInfoRow('Passing Score', '60%'),
                    ],
                  ),
                ),
              ),
              SizedBox(height: 32),
              SizedBox(
                width: double.infinity,
                height: 50,
                child: ElevatedButton.icon(
                  onPressed: () {
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) => QuizScreen(
                          questions: QuizData.getFlutterQuiz(),
                        ),
                      ),
                    );
                  },
                  icon: Icon(Icons.play_arrow),
                  label: Text(
                    'Start Quiz',
                    style: TextStyle(fontSize: 18),
                  ),
                  style: ElevatedButton.styleFrom(
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(12),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildInfoRow(String label, String value) {
    return Padding(
      padding: EdgeInsets.symmetric(vertical: 8),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(
            label,
            style: TextStyle(fontSize: 14),
          ),
          Text(
            value,
            style: TextStyle(
              fontSize: 14,
              fontWeight: FontWeight.bold,
            ),
          ),
        ],
      ),
    );
  }
}
10

Creating Quiz Screen

lib/screens/quiz_screen.dart

import 'package:flutter/material.dart';
import '../models/question.dart';
import '../models/quiz_result.dart';
import '../widgets/option_button.dart';
import '../widgets/progress_indicator.dart';
import 'result_screen.dart';

class QuizScreen extends StatefulWidget {
  final List questions;

  const QuizScreen({Key? key, required this.questions}) : super(key: key);

  @override
  _QuizScreenState createState() => _QuizScreenState();
}

class _QuizScreenState extends State {
  int _currentQuestionIndex = 0;
  Map _userAnswers = {}; // questionId -> selectedOptionIndex
  bool _showAnswer = false;

  Question get _currentQuestion => widget.questions[_currentQuestionIndex];
  bool get _isLastQuestion => _currentQuestionIndex == widget.questions.length - 1;
  bool get _isFirstQuestion => _currentQuestionIndex == 0;
  int? get _selectedAnswer => _userAnswers[_currentQuestion.id];

  void _selectAnswer(int index) {
    if (_showAnswer) return;

    setState(() {
      _userAnswers[_currentQuestion.id] = index;
      _showAnswer = true;
    });
  }

  void _nextQuestion() {
    if (_isLastQuestion) {
      _finishQuiz();
    } else {
      setState(() {
        _currentQuestionIndex++;
        _showAnswer = false;
      });
    }
  }

  void _previousQuestion() {
    if (!_isFirstQuestion) {
      setState(() {
        _currentQuestionIndex--;
        _showAnswer = false;
      });
    }
  }

  void _finishQuiz() {
    int correctAnswers = 0;
    int wrongAnswers = 0;

    for (var question in widget.questions) {
      final userAnswer = _userAnswers[question.id];
      if (userAnswer != null) {
        if (question.isCorrect(userAnswer)) {
          correctAnswers++;
        } else {
          wrongAnswers++;
        }
      } else {
        wrongAnswers++;
      }
    }

    final result = QuizResult(
      totalQuestions: widget.questions.length,
      correctAnswers: correctAnswers,
      wrongAnswers: wrongAnswers,
      userAnswers: _userAnswers,
      completedAt: DateTime.now(),
    );

    Navigator.pushReplacement(
      context,
      MaterialPageRoute(
        builder: (context) => ResultScreen(
          result: result,
          questions: widget.questions,
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Quiz'),
        actions: [
          if (!_isLastQuestion || _showAnswer)
            TextButton(
              onPressed: _finishQuiz,
              child: Text(
                'Finish',
                style: TextStyle(color: Colors.white),
              ),
            ),
        ],
      ),
      body: Column(
        children: [
          QuizProgressIndicator(
            currentQuestion: _currentQuestionIndex,
            totalQuestions: widget.questions.length,
          ),
          Expanded(
            child: SingleChildScrollView(
              padding: EdgeInsets.all(16),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Card(
                    child: Padding(
                      padding: EdgeInsets.all(20),
                      child: Text(
                        _currentQuestion.questionText,
                        style: TextStyle(
                          fontSize: 20,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ),
                  ),
                  SizedBox(height: 24),
                  ...List.generate(
                    _currentQuestion.options.length,
                    (index) => OptionButton(
                      option: _currentQuestion.options[index],
                      isSelected: _selectedAnswer == index,
                      isCorrect: _currentQuestion.correctAnswerIndex == index,
                      showAnswer: _showAnswer,
                      onTap: () => _selectAnswer(index),
                    ),
                  ),
                  if (_showAnswer && _currentQuestion.explanation != null) ...[
                    SizedBox(height: 24),
                    Card(
                      color: Colors.blue[50],
                      child: Padding(
                        padding: EdgeInsets.all(16),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Row(
                              children: [
                                Icon(Icons.lightbulb_outline, color: Colors.blue),
                                SizedBox(width: 8),
                                Text(
                                  'Explanation',
                                  style: TextStyle(
                                    fontSize: 16,
                                    fontWeight: FontWeight.bold,
                                    color: Colors.blue[900],
                                  ),
                                ),
                              ],
                            ),
                            SizedBox(height: 8),
                            Text(
                              _currentQuestion.explanation!,
                              style: TextStyle(color: Colors.blue[900]),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ],
                ],
              ),
            ),
          ),
          Padding(
            padding: EdgeInsets.all(16),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                ElevatedButton.icon(
                  onPressed: _isFirstQuestion ? null : _previousQuestion,
                  icon: Icon(Icons.arrow_back),
                  label: Text('Previous'),
                ),
                ElevatedButton.icon(
                  onPressed: _showAnswer
                      ? _nextQuestion
                      : (_selectedAnswer != null ? _nextQuestion : null),
                  icon: Icon(_isLastQuestion ? Icons.check : Icons.arrow_forward),
                  label: Text(_isLastQuestion ? 'Finish' : 'Next'),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}
11

Creating Result Screen

lib/screens/result_screen.dart

import 'package:flutter/material.dart';
import '../models/question.dart';
import '../models/quiz_result.dart';
import 'home_screen.dart';
import 'quiz_screen.dart';
import '../data/quiz_data.dart';

class ResultScreen extends StatelessWidget {
  final QuizResult result;
  final List questions;

  const ResultScreen({
    Key? key,
    required this.result,
    required this.questions,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Quiz Results'),
        automaticallyImplyLeading: false,
      ),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(24),
        child: Column(
          children: [
            // Score Card
            Card(
              color: _getScoreColor(),
              child: Padding(
                padding: EdgeInsets.all(24),
                child: Column(
                  children: [
                    Icon(
                      _getScoreIcon(),
                      size: 80,
                      color: Colors.white,
                    ),
                    SizedBox(height: 16),
                    Text(
                      '${result.percentage.toInt()}%',
                      style: TextStyle(
                        fontSize: 48,
                        fontWeight: FontWeight.bold,
                        color: Colors.white,
                      ),
                    ),
                    SizedBox(height: 8),
                    Text(
                      'Grade: ${result.grade}',
                      style: TextStyle(
                        fontSize: 24,
                        color: Colors.white,
                      ),
                    ),
                    SizedBox(height: 16),
                    Text(
                      result.feedback,
                      style: TextStyle(
                        fontSize: 16,
                        color: Colors.white,
                      ),
                      textAlign: TextAlign.center,
                    ),
                  ],
                ),
              ),
            ),
            SizedBox(height: 24),
            // Statistics
            Card(
              child: Padding(
                padding: EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Statistics',
                      style: TextStyle(
                        fontSize: 20,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    SizedBox(height: 16),
                    _buildStatRow('Total Questions', '${result.totalQuestions}'),
                    _buildStatRow('Correct Answers', '${result.correctAnswers}', Colors.green),
                    _buildStatRow('Wrong Answers', '${result.wrongAnswers}', Colors.red),
                    _buildStatRow('Unanswered', '${result.totalQuestions - result.userAnswers.length}', Colors.orange),
                  ],
                ),
              ),
            ),
            SizedBox(height: 24),
            // Review Section
            Card(
              child: Padding(
                padding: EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Review Answers',
                      style: TextStyle(
                        fontSize: 20,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    SizedBox(height: 16),
                    ...List.generate(
                      questions.length,
                      (index) => _buildQuestionReview(questions[index], index),
                    ),
                  ],
                ),
              ),
            ),
            SizedBox(height: 24),
            // Action Buttons
            Row(
              children: [
                Expanded(
                  child: OutlinedButton.icon(
                    onPressed: () {
                      Navigator.pushReplacement(
                        context,
                        MaterialPageRoute(
                          builder: (context) => QuizScreen(
                            questions: QuizData.getFlutterQuiz(),
                          ),
                        ),
                      );
                    },
                    icon: Icon(Icons.refresh),
                    label: Text('Retake Quiz'),
                  ),
                ),
                SizedBox(width: 16),
                Expanded(
                  child: ElevatedButton.icon(
                    onPressed: () {
                      Navigator.pushAndRemoveUntil(
                        context,
                        MaterialPageRoute(builder: (context) => HomeScreen()),
                        (route) => false,
                      );
                    },
                    icon: Icon(Icons.home),
                    label: Text('Home'),
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  Color _getScoreColor() {
    if (result.percentage >= 80) return Colors.green;
    if (result.percentage >= 60) return Colors.blue;
    return Colors.orange;
  }

  IconData _getScoreIcon() {
    if (result.percentage >= 80) return Icons.emoji_events;
    if (result.percentage >= 60) return Icons.check_circle;
    return Icons.sentiment_dissatisfied;
  }

  Widget _buildStatRow(String label, String value, [Color? valueColor]) {
    return Padding(
      padding: EdgeInsets.symmetric(vertical: 8),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(
            label,
            style: TextStyle(fontSize: 16),
          ),
          Text(
            value,
            style: TextStyle(
              fontSize: 16,
              fontWeight: FontWeight.bold,
              color: valueColor,
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildQuestionReview(Question question, int index) {
    final userAnswer = result.userAnswers[question.id];
    final isCorrect = userAnswer != null && question.isCorrect(userAnswer);

    return Card(
      margin: EdgeInsets.only(bottom: 12),
      color: isCorrect ? Colors.green[50] : Colors.red[50],
      child: Padding(
        padding: EdgeInsets.all(12),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Icon(
                  isCorrect ? Icons.check_circle : Icons.cancel,
                  color: isCorrect ? Colors.green : Colors.red,
                ),
                SizedBox(width: 8),
                Text(
                  'Question ${index + 1}',
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 16,
                  ),
                ),
              ],
            ),
            SizedBox(height: 8),
            Text(
              question.questionText,
              style: TextStyle(fontSize: 14),
            ),
            SizedBox(height: 8),
            if (userAnswer != null) ...[
              Text(
                'Your answer: ${question.options[userAnswer]}',
                style: TextStyle(
                  fontSize: 12,
                  color: isCorrect ? Colors.green[900] : Colors.red[900],
                ),
              ),
            ] else ...[
              Text(
                'Your answer: Not answered',
                style: TextStyle(
                  fontSize: 12,
                  color: Colors.orange[900],
                ),
              ),
            ],
            Text(
              'Correct answer: ${question.correctAnswer}',
              style: TextStyle(
                fontSize: 12,
                color: Colors.green[900],
                fontWeight: FontWeight.bold,
              ),
            ),
          ],
        ),
      ),
    );
  }
}
12

Updating Main.dart

lib/main.dart

import 'package:flutter/material.dart';
import 'screens/home_screen.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Quiz',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
        useMaterial3: true,
      ),
      home: HomeScreen(),
    );
  }
}
13

Project Checklist

Implementation Checklist

  • ✅ Project created and dependencies added
  • ✅ Folder structure organized
  • ✅ Question model created
  • ✅ Quiz result model with scoring logic
  • ✅ Quiz data with 10 sample questions
  • ✅ Option button widget with visual feedback
  • ✅ Progress indicator widget
  • ✅ Home screen with quiz information
  • ✅ Quiz screen with navigation and answer selection
  • ✅ Result screen with detailed feedback
  • ✅ Main.dart configured
14

Enhancement Ideas

Optional Enhancements

  • Add timer for each question or overall quiz
  • Implement different quiz categories
  • Add difficulty levels (easy, medium, hard)
  • Store quiz history locally
  • Add leaderboard functionality
  • Implement question shuffling
  • Add sound effects for correct/wrong answers
  • Create a question bank with more questions
  • Add image support for questions
  • Implement quiz sharing functionality
15

Exercises

1. Complete Implementation

Implement the entire quiz app following all the code provided. Test all features including question navigation, answer selection, and results display.

2. Add Timer

Add a countdown timer for each question (e.g., 30 seconds). If time runs out, automatically move to the next question and mark the current question as unanswered.

3. Add Categories

Create multiple quiz categories (e.g., Flutter Basics, Dart Language, State Management). Allow users to select a category before starting the quiz.